package cz.muni.fi.cfg.servlet;

import cz.muni.fi.cfg.conversions.Modes;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cz.muni.fi.cfg.parser.Parser;
import cz.muni.fi.cfg.parser.ParserException;
import cz.muni.fi.cfg.grammar.ContextFreeGrammar;
import cz.muni.fi.cfg.forms.Analyser;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author      Daniel Pelisek <dpelisek@gmail.com>
 * @version     1.0             
 * @since       2011-04-10
 */
public class Cyk extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        String teacherIS = request.getParameter("t");
//teacherIS = "CFG-CYK:baab:A->Aa'|Bb'|b'a', <Ab'>->Ab', B->Aa'|B<Ab'>|b'a', a'->a, b'->b";
        String studentIS = request.getParameter("s");

        String generateData = request.getParameter("generateData");
        String word = request.getParameter("word");

        boolean generateISString = Boolean.parseBoolean(request.getParameter("cykISString"));
        Modes mode = Modes.normal;

        if (teacherIS != null) {
            mode = Modes.simple;
            generateISString = false;
            // TODO: studentIS rosparsovat na tabulku
            String[] parsedArray = null;
            try {
                parsedArray = new Parser().parseCYKString(teacherIS);
            } catch (ParserException ex) {
                PrintWriter out = response.getWriter();
                try {
                    out.println("false");
                } finally {
                    out.close();
                }
            }
            word = parsedArray[0];
            generateData = parsedArray[1];
        }

        if (generateData == null || generateData.equals("")) {
            request.setAttribute("error3", "Nebyla zadána žádná gramatika.");
            request.getRequestDispatcher("/indexcfg.jsp").forward(request, response);
            return;
        }

        if (word == null || word.equals("")) {
            request.setAttribute("error3", "Nebylo zadáno žádné slovo.");
            request.getRequestDispatcher("/indexcfg.jsp").forward(request, response);
            return;
        }

        ContextFreeGrammar cfg = null;
        try {
            cfg = new Parser().parse(generateData);
        } catch (ParserException ex) {
            request.setAttribute("error3", ex.getMessage());
            request.getRequestDispatcher("/indexcfg.jsp").forward(request, response);
            return;
        }

        StringBuilder reason = new StringBuilder();
        if (!new Analyser().isInCNF(cfg, reason)) {
            request.setAttribute("error3", "Zadaná gramatika není v CNF. " + reason);
            request.getRequestDispatcher("/indexcfg.jsp").forward(request, response);
            return;
        }

        List<List<Set<String>>> studentTable = new ArrayList<List<Set<String>>>();
        List<List<Set<String>>> teacherTable = new Analyser().cyk(cfg, word);
        int n = word.length();
        for (int i = 0; i < n; i++) {
            studentTable.add(new ArrayList<Set<String>>());
            for (int j = 0; j < n - i; j++) {
                String cell = request.getParameter("t" + i + "-" + (10 - n + j));
                cell = cell.replace(" ", "");
                Set<String> cellSet = new HashSet<String>(Arrays.asList(cell.split(",")));
                if (cell.isEmpty()) {
                    cellSet.clear();
                }
                studentTable.get(i).add(cellSet);
            }
        }

        if (generateISString) {
            request.setAttribute("ISString", "b:CFG-CYK:" + word + ":" + cfg.toString().replace(" ", "").replace(",", ", ").replace("\n", "").replace("\r", ""));
        }

        if (mode.equals(Modes.simple)) {
            PrintWriter out = response.getWriter();
            try {
                out.println(studentTable.equals(teacherTable) ? "true" : "false");
            } finally {
                out.close();
            }
        } else {
            request.setAttribute("studentTable", studentTable);
            request.setAttribute("teacherTable", teacherTable);
            request.getRequestDispatcher("/resultgenerate.jsp").forward(request, response);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
